package com.todo.user.application.service.impl;

import cn.hutool.core.util.PhoneUtil;
import com.alibaba.fastjson.JSONObject;
import com.todo.common.common.entity.response.page.PageResult;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.enums.SourceEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.common.utils.TodoCommonUtils;
import com.todo.user.application.convert.UserServiceConvert;
import com.todo.user.application.entity.bo.UserAccountBO;
import com.todo.user.application.entity.bo.UserAccountConditionBO;
import com.todo.user.application.service.UserAccountService;
import com.todo.user.application.service.UserCacheService;
import com.todo.user.common.enums.UserStatusEnum;
import com.todo.user.infrastructure.entity.condition.UserAccountCondition;
import com.todo.user.infrastructure.entity.po.UserAccountPO;
import com.todo.user.infrastructure.repository.UserAccountRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;

/**
 * (UserAccount)表服务实现类
 *
 * @author zhangwenxiang
 * @since 2024-03-04 00:19:49
 */
@Slf4j
@Service
public class UserAccountServiceImpl implements UserAccountService {

    @Resource
    private UserAccountRepository userAccountRepository;
    @Resource
    private UserCacheService userCacheService;

    @Override
    public UserAccountBO queryUserAccount(String userName) {
        if (StringUtils.isBlank(userName)) {
            return null;
        }
        return userCacheService.getUserAccount(userName);
    }

    @Override
    public UserAccountBO queryUserAccountById(Long userId) {
        if (userId == null || userId < 0) {
            return null;
        }
        UserAccountPO userAccountPO = userAccountRepository.queryUserAccountPOById(userId);
        return UserServiceConvert.convertToUserAccountBO(userAccountPO);
    }

    @Override
    public UserAccountBO queryUserAccountByPhone(String phone) {
        if (StringUtils.isEmpty(phone)) {
            return null;
        }
        if (!PhoneUtil.isPhone(phone)) {
            log.error("UserAccountService#queryUserAccountById 手机号不合法，默认操作异常 phone：【{}】", phone);
            throw new BizException(BizErrorCodeEnum.INVALID_FORMAT);
        }
        UserAccountPO userAccountPO = userAccountRepository.queryUserAccountPOByPhone(phone);
        log.info("UserAccountService#queryUserAccountById 根据手机号查询账户信息完成 phone：【{}】，userAccountPO【{}】", phone, JSONObject.toJSONString(userAccountPO));
        return UserServiceConvert.convertToUserAccountBO(userAccountPO);
    }

    @Override
    public Boolean insertUserAccount(@NotNull String username, String phone, String password) {
        if (StringUtils.isBlank(username)) {
            return false;
        }
        UserAccountPO alreadyUserAccountPO = userAccountRepository.queryUserAccountPOByUserName(username);
        if (alreadyUserAccountPO != null) {
            log.warn("UserInfoService#insertUserAccount 新增用户信息失败，存在用户账号 username：【{}】", username);
            throw new BizException(BizErrorCodeEnum.SUCCESS_EXIST);
        }
        if (StringUtils.isNotEmpty(phone)) {
            if (!PhoneUtil.isPhone(phone)){
                log.warn("UserInfoService#insertUserAccount 新增用户信息失败，非正常手机号 phone：【{}】", phone);
                throw new BizException(BizErrorCodeEnum.PHONE_ERROR);
            }
            UserAccountPO phoneUserAccountPO = userAccountRepository.queryUserAccountPOByPhone(phone);
            if (phoneUserAccountPO != null){
                log.warn("UserInfoService#insertUserAccount 新增用户信息失败，存在手机号 phone：【{}】", phone);
                throw new BizException(BizErrorCodeEnum.PHONE_NUMBER_HAS_BEEN_USED);
            }
        }
        UserAccountPO userAccountPO = new UserAccountPO();
        fillDefaultUserAccountPO(userAccountPO, username, phone, password);
        Boolean insertResult = userAccountRepository.insertUserAccountPO(userAccountPO);
        return insertResult;
    }

    private void fillDefaultUserAccountPO(UserAccountPO userAccountPO, String username, String phone, String password) {
        userAccountPO.setId(TodoCommonUtils.buildLongGuid());
        userAccountPO.setUserName(username);
        //默认名称
        userAccountPO.setNickName("途度用户"+username);
        //默认头像
        userAccountPO.setHeadImg("默认头像");
        userAccountPO.setBackgroundImg("默认背景");
        userAccountPO.setStatus(UserStatusEnum.ACTIVATE.getType());
        userAccountPO.setIsReal(1);
        userAccountPO.setPassword(password);
        userAccountPO.setMobile(phone);
        //初期默认都是小程序来的用户
        userAccountPO.setSource(SourceEnum.APPLET.getType());
        userAccountPO.setIsDelete(0);
        userAccountPO.setCreateTime(new Date());
        userAccountPO.setUpdateTime(new Date());
    }

    @Override
    public Boolean updateUserSecret(String userName, String oldPassword, String newPassword) {
        if (StringUtils.isBlank(userName) || StringUtils.isEmpty(oldPassword) || StringUtils.isEmpty(newPassword)) {
            throw new BizException(BizErrorCodeEnum.USERNAME_OR_PASSWORD_ERROR);
        }
        //新旧密码校验
        if (oldPassword.equals(newPassword)) {
            log.warn("UserInfoService#updateUserSecret 新旧密码校验是失败，新旧密码相同不允许修改 userName：【{}】", userName);
            throw new BizException(BizErrorCodeEnum.SAME_PASSWORD);
        }
        //是否存在用户信息
        UserAccountPO userAccountPO = userAccountRepository.queryUserAccountPOByUserName(userName);
        if (userAccountPO == null) {
            log.warn("UserInfoService#updateUserSecret 当前用户名称不存在实际用户，不允许操作 userName：【{}】", userName);
            throw new BizException(BizErrorCodeEnum.USER_DOES_NOT_EXISTS);
        }
        //旧密码是否一致
        String password = userAccountPO.getPassword();
        if (!oldPassword.equals(password)) {
            log.warn("UserInfoService#updateUserSecret 新旧密码校验是失败，当前用户密码和旧密码不一致，登录异常 userName：【{}】", userName);
            throw new BizException(BizErrorCodeEnum.PASSWORD_ERROR);
        }
        Boolean updateResult = userAccountRepository.updateUserSecret(userAccountPO.getId(), newPassword);
        if (updateResult){
            userCacheService.removeUserCache(userName);
        }
        return updateResult;
    }

    @Override
    public Boolean removeUserAccount(String userName) {
        if (StringUtils.isBlank(userName)) {
            return false;
        }
        UserAccountBO userAccountBO = queryUserAccount(userName);
        if (userAccountBO == null) {
            return true;
        }
        Boolean removeResult = userAccountRepository.removeUserAccountPOById(userAccountBO.getId());
        if (removeResult) {
            //清除用户信息完成 清除缓存、token等
            userCacheService.removeUserCache(userName);
        }
        return removeResult;
    }

    @Override
    public Boolean mutedUserAccountById(Long userId, UserStatusEnum userStatusEnum, String reason) {
        if (userId == null || userStatusEnum == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        UserAccountPO userAccountPO = userAccountRepository.queryUserAccountPOById(userId);
        if (userAccountPO == null) {
            log.warn("UserAccountService#mutedUserAccountById 用户状态调整失败 当前用户不存在 userId:【{}】", userId);
            return false;
        }
        if (userAccountPO.getStatus().equals(userStatusEnum.getType())) {
            return true;
        }
        Boolean result = userAccountRepository.updateUserStatusById(userId, userStatusEnum.getType(), reason);
        return result;
    }

    @Override
    public PageResult<UserAccountBO> queryUserAccountByCondition(UserAccountConditionBO conditionBO) {
        if (conditionBO == null) {
            return PageResult.of(new ArrayList<>(), 0, 0, 0);
        }
        UserAccountCondition condition = UserServiceConvert.convertToUserAccountCondition(conditionBO);
        PageResult<UserAccountPO> userAccountPOPageResult = userAccountRepository.queryUserAccountPOByCondition(condition);
        return UserServiceConvert.convertToPageUserAccountBO(userAccountPOPageResult);
    }


}
